import java.util.Arrays;

public class Polygon extends ClosedFigure
{
    private Point[] points;

    public Polygon(Point[] points)
    {
        super("多边形",points[0]);
        this.points=points.clone();
        if(this.points.length<3) throw new IllegalArgumentException(("length is "+this.points.length+" but the minimum should be 3"));
        boolean flag=true;
        Line l=new Line(this.points[0],this.points[1]);
        for(int i=2;i<this.points.length&&flag;flag&=l.contains(this.points[i]),++i) ;
        if(flag)
            throw new IllegalArgumentException(("All the points on the same line "+this.toStringPoints()));
    }

    public Polygon()
    {
        this(new Point[]{new Point(0,0),new Point(0,1),new Point(1,0),});
    }

    public Polygon(Polygon p)
    {
        this(p.points);
    }

    //    public String toString()
//    {
//        return "Polygon{"+
//                "shape='"+shape+'\''+
//                ", point1="+point1+
//                ", points="+Arrays.toString(points)+
//                '}';
//    }
    protected String toStringPoints()
    {
        String s="new Point[]{";
        for(int i=0;i<points.length;++i)
            s+=(i==0?"":",")+points[i];
        s+="}";
        return s;
    }

    public String toString()
    {
        return "new Polygon("+toStringPoints()+")";
    }

    public double perimeter()
    {
        double perim=0;
        for(int i=0;i<points.length;++i)
            perim+=new Line(points[i],points[(i+1)%points.length]).length();
        return perim;
    }

    public double area()
    {
        double sum=0;
        for(int i=1;i<points.length-1;++i)
            sum+=new Triangle(points[0],points[i],points[i+1]).area();
        return sum;
    }

    public Polygon revolve(double angle)
    {
        return revolve(points[0],angle);
    }

    public Polygon revolve(Point p,double angle)
    {
        Polygon a=new Polygon(this);
        for(int i=0;i<points.length;++i)
            a.points[i]=a.points[i].revolve(p,angle);
        return a;
    }

    public Polygon zoom(double angle)
    {
        return zoom(points[0],angle);
    }

    public Polygon zoom(Point p,double angle)
    {
        Polygon a=new Polygon(this);
        for(int i=0;i<points.length;++i)
            a.points[i]=a.points[i].zoom(p,angle);
        return a;
    }

    public boolean contains(Point p)
    {
        //这可不大好写，给一个参考文献
        //[1]https://blog.csdn.net/WilliamSun0122/article/details/77994526
        //文献指出
        //前一个判断min(P1.y,P2.y)<P.y<=max(P1.y,P2.y)
        //这个判断代码我觉得写的很精妙 我网上看的 应该是大神模版
        //后一个判断被测点 在 射线与边交点 的左边
        //if( (dcmp(P1.y-P.y)>0 != dcmp(P2.y-P.y)>0) && dcmp(P.x - (P.y-P1.y)*(P1.x-P2.x)/(P1.y-P2.y)-P1.x)<0)
        //  flag = !flag;
        //第一坨说min(P1.y,P2.y)<P.y<=max(P1.y,P2.y)，我觉得是对的，他水平做线必须这个点在纵坐标之间才能相交
        //第二坨虽然他觉得很精妙，但我不这么觉得，他这个玩意表达的实际上是P.x < (P.y-P1.y)*(P1.x-P2.x)/(P1.y-P2.y)+P1.x
        //也就是求了直线P1P2和水平射线的交点的横坐标
        //但是他相当于用了斜截式，所以处理不了竖着的情况，而我的Line.intersects因为用了标准式，所以可以处理竖着的情况
        boolean flag=false;
        for(int i=0, j=points.length-1;i<points.length;j=i,++i)
        {
            if(new Line(points[i],points[j]).onSegment(p))//点P在边ij上
                return true;
            if((MyMath.compareDouble(points[i].getY(),p.getY())>0!=MyMath.compareDouble(points[j].getY(),p.getY())>0)&&
                    p.getX()<new Line(points[i],points[j]).intersects(new Line(p,new Point(p.getX()+1,p.getY())))
                                                          .getX())
                flag=!flag;
        }
        return flag;
    }
}
